{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "k91y6QPYeq_z"
   },
   "source": [
    "# Chapter 7 - Classes - 類別"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "sqOS3crNmHH-"
   },
   "source": [
    "在前面的章節中，我們使用了相當多內建的物件，並調用物件的方法做出許多應用。\n",
    "\n",
    "接下來開始可以製作我們需要的物件類別 (Classes)。類別可以想像為物件的範本，裡面可以定義類別的建構子 (Constructor)、屬性 (Attributes) 及方法 (Methods)，最後用這個範本去產生物件實例 (Instances)。\n",
    "\n",
    "物件類別之間還可以繼承 (Inherit)，讓物件之間可以保留部分相同的成分，並對不同的成分做出微調。\n",
    "\n",
    "這些都是物件導向 (Object-oriented) 程式設計中相當重要的概念。筆者喜歡以貓科動物的類別來當例子，用以講解物件類別設定及繼承的概念，希望可以讓各位讀者更容易理解。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "t1ulxeALkYwh"
   },
   "source": [
    "References:\n",
    "\n",
    "* [Classes - Python Documentation](https://docs.python.org/3/tutorial/classes.html)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "2115_vnDkqee"
   },
   "source": [
    "## 建立物件類別 (Classes) 及物件實例 (Instances)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "7odfOYWurZwf"
   },
   "source": [
    "用關鍵字 `class` 來定義一個新的物件類別。物件類別名稱的首字並定要為大寫英文字："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {
    "executionInfo": {
     "elapsed": 782,
     "status": "ok",
     "timestamp": 1607840017461,
     "user": {
      "displayName": "黃種平",
      "photoUrl": "https://lh3.googleusercontent.com/a-/AOh14GjCoYcYDAMAK-J-MvClxwWJY0fvKYsny6BL962ZNA=s64",
      "userId": "12486487678081777487"
     },
     "user_tz": -480
    },
    "id": "9OdWSSWKoEY6"
   },
   "outputs": [],
   "source": [
    "class Cat:  # 建立新的物件類別 Cat（貓類別）\n",
    "    pass    # 暫時不撰寫內容"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "rizcihWVr92b"
   },
   "source": [
    "接著將物件類別指定到一個新的物件上，來初始化 (Initialize) 這個類別的一個物件。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/"
    },
    "executionInfo": {
     "elapsed": 785,
     "status": "ok",
     "timestamp": 1607839503199,
     "user": {
      "displayName": "黃種平",
      "photoUrl": "https://lh3.googleusercontent.com/a-/AOh14GjCoYcYDAMAK-J-MvClxwWJY0fvKYsny6BL962ZNA=s64",
      "userId": "12486487678081777487"
     },
     "user_tz": -480
    },
    "id": "Ur7KmCBkoHS7",
    "outputId": "2dd0a905-be9e-4349-9a9a-1ebe0d8eb72a"
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "<class '__main__.Cat'>\n"
     ]
    }
   ],
   "source": [
    "cat = Cat()       # 建立一個新的物件 cat（一隻貓），而 cat 物件是由類別 Cat 初始化而來\n",
    "                  # 括號內可傳入參數至建構子內，會在下一個小節講解\n",
    "print(type(cat))  # 驗證此物件的類別"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "POzmqeALpLO9"
   },
   "source": [
    "## 建構子 (Constructor)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "IUqiAx_8tQzr"
   },
   "source": [
    "一般在建立一個類別時，會一併製作建構子，用途是在初始化類別實例時，設定可以一併執行的操作，或透過傳入參數來設定新的物件中的組成。\n",
    "\n",
    "> 備註：其實 Python 並沒有建構子 (Constructor) 的定義，但類別中的 `__init__()` 方法與其他的程式語言中的建構子的功能是一致的，所以在這裡借用其他程式語言的稱呼。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {
    "executionInfo": {
     "elapsed": 1015,
     "status": "ok",
     "timestamp": 1607840122523,
     "user": {
      "displayName": "黃種平",
      "photoUrl": "https://lh3.googleusercontent.com/a-/AOh14GjCoYcYDAMAK-J-MvClxwWJY0fvKYsny6BL962ZNA=s64",
      "userId": "12486487678081777487"
     },
     "user_tz": -480
    },
    "id": "cDwledWVpNX_"
   },
   "outputs": [],
   "source": [
    "class Cat:\n",
    "    def __init__(self):              # Cat 貓類別的建構子\n",
    "        print(\"A new cat is born!\")  # 當實例被建立時，提示有一隻新的貓出生了！"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/"
    },
    "executionInfo": {
     "elapsed": 1133,
     "status": "ok",
     "timestamp": 1607840122859,
     "user": {
      "displayName": "黃種平",
      "photoUrl": "https://lh3.googleusercontent.com/a-/AOh14GjCoYcYDAMAK-J-MvClxwWJY0fvKYsny6BL962ZNA=s64",
      "userId": "12486487678081777487"
     },
     "user_tz": -480
    },
    "id": "Ikxx-gOCpS2Y",
    "outputId": "f6d4da8a-456e-4838-b85b-0e9c4aa6e685"
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "A new cat is born!\n"
     ]
    }
   ],
   "source": [
    "cat = Cat()  # 初始化一隻貓"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "omiVVeC_oNYR"
   },
   "source": [
    "## 屬性 (Attributes)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "y95mXsClvlbw"
   },
   "source": [
    "上一個小節有提到：建構子通常也用來在初始化物件時，用傳入參數的方式來定義一個物件的組成。我們用貓類別當做例子，每隻貓會有不同的花色、身長、重量，透過建構子即可輕易的在初始化時將一隻貓的屬性給定義好。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {
    "executionInfo": {
     "elapsed": 698,
     "status": "ok",
     "timestamp": 1607840960586,
     "user": {
      "displayName": "黃種平",
      "photoUrl": "https://lh3.googleusercontent.com/a-/AOh14GjCoYcYDAMAK-J-MvClxwWJY0fvKYsny6BL962ZNA=s64",
      "userId": "12486487678081777487"
     },
     "user_tz": -480
    },
    "id": "Rm8JBABWoQEN"
   },
   "outputs": [],
   "source": [
    "class Cat:\n",
    "    def __init__(self, color, height, weight):  # 在建構子中定義三個要傳入的屬性：花色、身長、重量\n",
    "        self.color = color                      # color 為傳入的屬性值，將其指定給此物件的屬性值 self.color\n",
    "        self.height = height                    # height 為傳入的屬性值，將其指定給此物件的屬性值 self.height\n",
    "        self.weight = weight                    # weight 為傳入的屬性值，將其指定給此物件的屬性值 self.weight"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "yzmvmbGlx4u9"
   },
   "source": [
    "> 備註：在類別定義中，所有方法都要傳入 `self` 物件，但在初始化時即可忽略。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {
    "executionInfo": {
     "elapsed": 819,
     "status": "ok",
     "timestamp": 1607840991505,
     "user": {
      "displayName": "黃種平",
      "photoUrl": "https://lh3.googleusercontent.com/a-/AOh14GjCoYcYDAMAK-J-MvClxwWJY0fvKYsny6BL962ZNA=s64",
      "userId": "12486487678081777487"
     },
     "user_tz": -480
    },
    "id": "SYN4QZ3yoSGS"
   },
   "outputs": [],
   "source": [
    "cat = Cat('white', 20, 2)  # 初始化新的貓，並將花色、身長、重量屬性設定值傳入"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/"
    },
    "executionInfo": {
     "elapsed": 827,
     "status": "ok",
     "timestamp": 1607841200577,
     "user": {
      "displayName": "黃種平",
      "photoUrl": "https://lh3.googleusercontent.com/a-/AOh14GjCoYcYDAMAK-J-MvClxwWJY0fvKYsny6BL962ZNA=s64",
      "userId": "12486487678081777487"
     },
     "user_tz": -480
    },
    "id": "kxxCyTTzpzjV",
    "outputId": "da921e3a-63d8-4da5-9714-6cf359588f00"
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "white\n"
     ]
    }
   ],
   "source": [
    "print(cat.color)  # 調用貓物件的屬性值\n",
    "                  # 注意：因為屬性不會接入傳入參數，所以屬性名稱之後不用加上括號 \"()\""
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/"
    },
    "executionInfo": {
     "elapsed": 1356,
     "status": "ok",
     "timestamp": 1607841124540,
     "user": {
      "displayName": "黃種平",
      "photoUrl": "https://lh3.googleusercontent.com/a-/AOh14GjCoYcYDAMAK-J-MvClxwWJY0fvKYsny6BL962ZNA=s64",
      "userId": "12486487678081777487"
     },
     "user_tz": -480
    },
    "id": "-iSsJgEDoTmE",
    "outputId": "c020fbcf-a6c7-441c-df3a-842a27d3c977"
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "The color of this cat is white\n",
      "The height of this cat is 20 cm\n",
      "The weight of this cat is 2 kg\n"
     ]
    }
   ],
   "source": [
    "# 嘗試調用所有貓物件的屬性值\n",
    "print(\"The color of this cat is\", cat.color)\n",
    "print(\"The height of this cat is\", str(cat.height), \"cm\")\n",
    "print(\"The weight of this cat is\", str(cat.weight), \"kg\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/"
    },
    "executionInfo": {
     "elapsed": 776,
     "status": "ok",
     "timestamp": 1607841117568,
     "user": {
      "displayName": "黃種平",
      "photoUrl": "https://lh3.googleusercontent.com/a-/AOh14GjCoYcYDAMAK-J-MvClxwWJY0fvKYsny6BL962ZNA=s64",
      "userId": "12486487678081777487"
     },
     "user_tz": -480
    },
    "id": "qdrMBeBPzBQk",
    "outputId": "a58df344-d594-4a0a-f667-9aebb9c1b7a7"
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "['__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', 'color', 'height', 'weight']\n"
     ]
    }
   ],
   "source": [
    "print(dir(cat))  # 查看貓物件的所有可執行操作"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "W0dtfJjXpoj3"
   },
   "source": [
    "## 方法 (Methods)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "M4WBe3CA2MpC"
   },
   "source": [
    "方法 (Methods) 其實就是：附加在物件上的函式。也因為附加在物件上，所以方法內通常會搭配調用物件本身的屬性值，來執行各式各樣的操作。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {
    "executionInfo": {
     "elapsed": 879,
     "status": "ok",
     "timestamp": 1607842357958,
     "user": {
      "displayName": "黃種平",
      "photoUrl": "https://lh3.googleusercontent.com/a-/AOh14GjCoYcYDAMAK-J-MvClxwWJY0fvKYsny6BL962ZNA=s64",
      "userId": "12486487678081777487"
     },
     "user_tz": -480
    },
    "id": "6Ypwz0ypeh8l"
   },
   "outputs": [],
   "source": [
    "class Cat:\n",
    "    def __init__(self, color, height, weight):\n",
    "        self.color = color\n",
    "        self.height = height\n",
    "        self.weight = weight\n",
    "    \n",
    "    def roar(self):     # 幫貓類別定義「吼叫」的方法\n",
    "        print(\"Meow!\")  # 發出叫聲\n",
    "        return \"Meow!\"  # 回傳叫聲內容\n",
    "    \n",
    "    def describe(self):                                # 幫貓類別定義「描述」方法\n",
    "        print(\"My color is\", self.color)               # 描述這隻貓自己的花色\n",
    "        print(\"My height is\", str(self.height), \"cm\")  # 描述這隻貓自己的身長\n",
    "        print(\"My weight is\", str(self.weight), \"kg\")  # 描述這隻貓自己的重量"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {
    "executionInfo": {
     "elapsed": 1203,
     "status": "ok",
     "timestamp": 1607842358297,
     "user": {
      "displayName": "黃種平",
      "photoUrl": "https://lh3.googleusercontent.com/a-/AOh14GjCoYcYDAMAK-J-MvClxwWJY0fvKYsny6BL962ZNA=s64",
      "userId": "12486487678081777487"
     },
     "user_tz": -480
    },
    "id": "4KXwflx-mpfL"
   },
   "outputs": [],
   "source": [
    "cat = Cat('white', 20, 2)  # 初始化一隻貓"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/"
    },
    "executionInfo": {
     "elapsed": 1181,
     "status": "ok",
     "timestamp": 1607842358298,
     "user": {
      "displayName": "黃種平",
      "photoUrl": "https://lh3.googleusercontent.com/a-/AOh14GjCoYcYDAMAK-J-MvClxwWJY0fvKYsny6BL962ZNA=s64",
      "userId": "12486487678081777487"
     },
     "user_tz": -480
    },
    "id": "4VvdOQ-3nLqd",
    "outputId": "42e18c88-c1bd-4642-dc12-2c89105e993a"
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Meow!\n"
     ]
    }
   ],
   "source": [
    "cat_sound = cat.roar()  # 讓貓吼叫，並將叫聲記錄於物件內"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/"
    },
    "executionInfo": {
     "elapsed": 638,
     "status": "ok",
     "timestamp": 1606982477223,
     "user": {
      "displayName": "黃種平",
      "photoUrl": "https://lh3.googleusercontent.com/a-/AOh14GjCoYcYDAMAK-J-MvClxwWJY0fvKYsny6BL962ZNA=s64",
      "userId": "12486487678081777487"
     },
     "user_tz": -480
    },
    "id": "ehK5EFmYnee4",
    "outputId": "4eb7b5e4-fdce-432d-e4c9-511e2255fd04"
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Meow!\n"
     ]
    }
   ],
   "source": [
    "print(cat_sound)  # 顯示貓的叫聲"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/"
    },
    "executionInfo": {
     "elapsed": 678,
     "status": "ok",
     "timestamp": 1607842391429,
     "user": {
      "displayName": "黃種平",
      "photoUrl": "https://lh3.googleusercontent.com/a-/AOh14GjCoYcYDAMAK-J-MvClxwWJY0fvKYsny6BL962ZNA=s64",
      "userId": "12486487678081777487"
     },
     "user_tz": -480
    },
    "id": "s2svrV-1nf6L",
    "outputId": "f2fca84c-1e30-48de-95a6-aec122a495fa"
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "My color is white\n",
      "My height is 20 cm\n",
      "My weight is 2 kg\n"
     ]
    }
   ],
   "source": [
    "cat.describe()  # 讓貓描述自己的花色、身長、體重"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "EVKCoQcEnhj5"
   },
   "source": [
    "## 繼承 (Inheritance)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "Pd7XR3UK3_K9"
   },
   "source": [
    "物件之間若有某些程度的相似性，可以用繼承的方式，在建立一個新的物件的同時，將同樣的成分直接保留，並加上或修改不同的成分。\n",
    "\n",
    "在此用老虎類別來舉例：老虎也是貓科動物，所以貓有的屬性，老虎也都有，也可以描述自己的花色、身長、體重，但是吼叫聲可能不同。所以我們在建立老虎類別時，可以先從貓類別繼承，之後改寫老虎的吼叫聲就好。\n",
    "\n",
    "這個貓類別與老虎類別的關係中：\n",
    "\n",
    "* Cat 貓類別為 Tiger 老虎類別的**父類別**或**親類別** (Parent class)\n",
    "* Tiger 老虎類別為 Cat 貓類別的**子類別** (Child class)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "metadata": {
    "executionInfo": {
     "elapsed": 876,
     "status": "ok",
     "timestamp": 1607842532117,
     "user": {
      "displayName": "黃種平",
      "photoUrl": "https://lh3.googleusercontent.com/a-/AOh14GjCoYcYDAMAK-J-MvClxwWJY0fvKYsny6BL962ZNA=s64",
      "userId": "12486487678081777487"
     },
     "user_tz": -480
    },
    "id": "gqu_Zr9-qEvq"
   },
   "outputs": [],
   "source": [
    "class Tiger(Cat):    # 老虎也是貓科動物，所以貓有的屬性老虎也會有，用繼承就不用改寫這些屬性\n",
    "    def roar(self):  # 但老虎跟貓的叫聲有相當大的差異，所以我們只改寫這個部分\n",
    "        print(\"Ahhhhhhh!\")\n",
    "        return \"Ahhhhhhh!\""
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "metadata": {
    "executionInfo": {
     "elapsed": 894,
     "status": "ok",
     "timestamp": 1607842547995,
     "user": {
      "displayName": "黃種平",
      "photoUrl": "https://lh3.googleusercontent.com/a-/AOh14GjCoYcYDAMAK-J-MvClxwWJY0fvKYsny6BL962ZNA=s64",
      "userId": "12486487678081777487"
     },
     "user_tz": -480
    },
    "id": "rDg4BuTGsp3-"
   },
   "outputs": [],
   "source": [
    "tiger = Tiger(color=\"yellow\", height=180, weight=100)  # 初始化一隻老虎"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/"
    },
    "executionInfo": {
     "elapsed": 806,
     "status": "ok",
     "timestamp": 1607842555674,
     "user": {
      "displayName": "黃種平",
      "photoUrl": "https://lh3.googleusercontent.com/a-/AOh14GjCoYcYDAMAK-J-MvClxwWJY0fvKYsny6BL962ZNA=s64",
      "userId": "12486487678081777487"
     },
     "user_tz": -480
    },
    "id": "hRoyJO17ssAc",
    "outputId": "9aa91938-b79a-421c-9a72-0a2090627ddd"
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Ahhhhhhh!\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "'Ahhhhhhh!'"
      ]
     },
     "execution_count": 17,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "tiger.roar()  # 讓老虎吼叫"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/"
    },
    "executionInfo": {
     "elapsed": 1020,
     "status": "ok",
     "timestamp": 1607842572284,
     "user": {
      "displayName": "黃種平",
      "photoUrl": "https://lh3.googleusercontent.com/a-/AOh14GjCoYcYDAMAK-J-MvClxwWJY0fvKYsny6BL962ZNA=s64",
      "userId": "12486487678081777487"
     },
     "user_tz": -480
    },
    "id": "SnLCQPPGtCqS",
    "outputId": "d9b19fcb-40dd-4318-8534-b12b1a4acc61"
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "My color is yellow\n",
      "My height is 180 cm\n",
      "My weight is 100 kg\n"
     ]
    }
   ],
   "source": [
    "tiger.describe()  # 讓老虎跟貓一樣，描述自己的屬性值"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "Xalywr-NtGVU"
   },
   "source": [
    "> 備註：或許在某些教學中，會看到建立親類別時，都會去繼承 `object` 物件："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "metadata": {
    "id": "ZaBd0wXD6dzo"
   },
   "outputs": [],
   "source": [
    "class Unknown(object):  # Unknown 繼承 object 類別\n",
    "    pass"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "7FKIGRAP7Xxt"
   },
   "source": [
    "> 這樣的寫法是基於「Python 裡的所有內容都是一種物件 (`object`)」，所以所有物件都是 `object` 類別的子物件。\n",
    ">\n",
    "> 但其實不需要特別去繼承 `object` 類別也沒有影響。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "z1WB1xyP79_f"
   },
   "source": [
    "## `super()`：調用親類別的內容"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "_6BFnU7K8HWj"
   },
   "source": [
    "如果在子類別中需要調用親類別的屬性或方法，可以調用 `super()` 函式，來指向親類別物件。\n",
    "\n",
    "我們用另一個獅子 Lion 類別來舉例：獅子也是貓科動物，但這次我們需要在建構子當中，額外定義一個 `king` 屬性，來標示這隻獅子是否為獅子王。所以建構子需要被部分改寫："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 20,
   "metadata": {
    "executionInfo": {
     "elapsed": 945,
     "status": "ok",
     "timestamp": 1607843972433,
     "user": {
      "displayName": "黃種平",
      "photoUrl": "https://lh3.googleusercontent.com/a-/AOh14GjCoYcYDAMAK-J-MvClxwWJY0fvKYsny6BL962ZNA=s64",
      "userId": "12486487678081777487"
     },
     "user_tz": -480
    },
    "id": "q-lXW81A8U0I"
   },
   "outputs": [],
   "source": [
    "class Lion(Cat):\n",
    "    def __init__(self, color, height, weight, king):  # 改寫建構子，多傳入一個 king 參數\n",
    "        super().__init__(color, height, weight)                  # 將 king 以外的參數傳給親類別建構子處理\n",
    "        self.king = king                              # 在 Lion 類別中自行處理 king 的屬性指定\n",
    "    \n",
    "    def roar(self):\n",
    "        print(\"Rahhhhhhhhh!\")\n",
    "        return \"Rahhhhhhhhh!\""
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 21,
   "metadata": {
    "executionInfo": {
     "elapsed": 731,
     "status": "ok",
     "timestamp": 1607843972962,
     "user": {
      "displayName": "黃種平",
      "photoUrl": "https://lh3.googleusercontent.com/a-/AOh14GjCoYcYDAMAK-J-MvClxwWJY0fvKYsny6BL962ZNA=s64",
      "userId": "12486487678081777487"
     },
     "user_tz": -480
    },
    "id": "NG2ISI-y9XfB"
   },
   "outputs": [],
   "source": [
    "lion = Lion(  # 初始化一隻獅子\n",
    "    color='brown',\n",
    "    height=200,\n",
    "    weight=120,\n",
    "    king=True\n",
    ")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 22,
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/"
    },
    "executionInfo": {
     "elapsed": 735,
     "status": "ok",
     "timestamp": 1607843997346,
     "user": {
      "displayName": "黃種平",
      "photoUrl": "https://lh3.googleusercontent.com/a-/AOh14GjCoYcYDAMAK-J-MvClxwWJY0fvKYsny6BL962ZNA=s64",
      "userId": "12486487678081777487"
     },
     "user_tz": -480
    },
    "id": "sle9CxOh9n-X",
    "outputId": "c036b747-7847-486d-ef88-172e2000cdee"
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "True"
      ]
     },
     "execution_count": 22,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "lion.king  # 檢查這隻獅子是不是獅子王"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 23,
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/"
    },
    "executionInfo": {
     "elapsed": 702,
     "status": "ok",
     "timestamp": 1607844012363,
     "user": {
      "displayName": "黃種平",
      "photoUrl": "https://lh3.googleusercontent.com/a-/AOh14GjCoYcYDAMAK-J-MvClxwWJY0fvKYsny6BL962ZNA=s64",
      "userId": "12486487678081777487"
     },
     "user_tz": -480
    },
    "id": "QWPg0ifs-GNp",
    "outputId": "1f4e0276-31d8-464a-ba71-9788f6b00fb2"
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "My color is brown\n",
      "My height is 200 cm\n",
      "My weight is 120 kg\n"
     ]
    }
   ],
   "source": [
    "lion.describe()  # 讓獅子描述自己的屬性"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "id": "kzPi0hPm-J4H"
   },
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "colab": {
   "authorship_tag": "ABX9TyNLzs/eOzcmPrx8gv64hVqi",
   "collapsed_sections": [],
   "name": "Python Basics - Chapter 7 - Classes.ipynb",
   "provenance": [],
   "toc_visible": true
  },
  "jupytext": {
   "formats": "ipynb,py:light"
  },
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.6.9"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 4
}
